/************************************************************
  Copyright (C), 2004-2018, Sumavision Tech. Co., Ltd.
  FileName: console.c
  Author:   dongjiawei  Date: 2018.01.25    Version: 0.0.1
  Description:this process handle 
              1)notification rpc, make sure will notify proper process. 
              2)running status, print warning logs and turn on/off warning lights.   
  History:         
      <author>     <time>       <version >   <desc>
      lixueliang    2018.02.26   0.0.2       Add mechanism of notification dispose
      lixueliang    2018.03.06   1.0.0       Test and realease
      lixueliang    2018.08.27   1.0.1       rewrite notify request rpc make up
      lixueliang    2018.12.05   1.0.2       optimize code structure
***********************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <ctype.h>

#include "od_engine.h"
#include "param_msg.h"
#include "message.h"
#include "param_json.h"
#include "other2json.h"

#include "rpc_response.h"
#include "console_param.h"
#include "param_rpc.h"
//#include "param_map.h"

#define RECV_DATA_LEN       (1024*1024)
#define SAME_STR             0
#define REQUEST_RPC_NUM      5

#define MAX_PARAM_NUM       6
#define NOTIFY_REQ_ID        "console_notify"

typedef struct notify_table_s{
    int data_type;
    const char *notify_key;
    int param_num;
    char *param_id[MAX_PARAM_NUM];
}notify_table_t;

enum {
    NETWORK_NOTIFY_LOCAL_IP = 0,
    NOTIFY_ITEM_NUMS,
} notify_ids;

static notify_table_t notify_table[]= 
{
    {PT_STRI_, "ipaddr", 0, {}},
};

static int notification_receiveandparse(od_msg_handle msg_handle, od_msg_t *msg,  jsonrpc_request_t *request)
{
    int ret = OD_ERROR;
    int recv_len = 0;
    struct json_object * jobj_rpc = NULL;

    msg->data_len = 5*RECV_DATA_LEN;
    recv_len = od_msg_receive(msg_handle, msg, MSG_MQ_WAIT_FOREVER);
    if(recv_len <= 0)
    {
        RPTDBG("core_app receive  msg length error. recv_len %d\n", recv_len);
        return ret;
    }

    ret = jsonrpc_jstr2jobj(msg->data, &jobj_rpc);
    if(ret != OD_OK)
    {
        RPTERR("recieve msg.data error");
        return ret;
    }

    ret = jsonrpc_request_parse(jobj_rpc, request);
    if(ret != OD_OK)
    {
        RPTERR("recieve jobj_rpc  is error, ERROR CODE:%d !", ret);
        return ret;
    }

    if((request->id == NULL)&&(request->method != NULL))
    {
        RPTDBG("jsonrpc is  notification! %s",json_object_get_string(jobj_rpc));
        return OD_OK;
    }
    else
    {
        RPTERR("recieve notification error!");
        return OD_ERROR;
    }
}

static int generate_request_rpc(json_object *notify_params_member_jobj, notify_table_t *notify_elem, struct json_object *request_rpc[])
{
    int request_rpc_num = 0;
    struct json_object *request_params_member_item_jobj = NULL;
    int32_t v_int = 0;
    char *ipaddr_str = NULL;
    int i;

    if(TRUE == json_object_object_get_ex(notify_params_member_jobj,
                                         notify_elem->notify_key,
                                         &request_params_member_item_jobj))
    {
        if(PT_SINT_ == notify_elem->data_type)
        {
            v_int = json_object_get_int(request_params_member_item_jobj);
            request_rpc[request_rpc_num] = param_id2rpc_set(*notify_elem->param_id, PT_SINT_, &v_int, NOTIFY_REQ_ID);
            request_rpc_num += 1;
        }
        else
        {
            ipaddr_str = (char *)od_calloc(1, strlen(json_object_get_string(request_params_member_item_jobj)) + 1);
            strncpy(ipaddr_str,
                    json_object_get_string(request_params_member_item_jobj),
                    strlen(json_object_get_string(request_params_member_item_jobj)));
            for(i = 0; i < notify_elem->param_num; i++)
            {
                request_rpc[request_rpc_num] = param_id2rpc_set(notify_elem->param_id[i], PT_STRI_, ipaddr_str, NOTIFY_REQ_ID);
                request_rpc_num += 1;
            }
            od_free(ipaddr_str);
       }

       return request_rpc_num;
    }

    return request_rpc_num;
}

static int makeup_request_rpc(const char *notify_method, struct json_object *notify_params, struct json_object *request_rpc[])
{
    int request_rpc_num = 0;
    int i;
    struct json_object *notify_params_member_jobj = NULL;
    struct json_object *notify_params_member_item_jobj = NULL;
    char *net_notify_params = "eth0";

    /*the notify method is "net.notify"*/
    if(SAME_STR == strcmp("net.notify", notify_method))
    {
        json_object_object_get_ex(notify_params, "net", &notify_params_member_jobj);
        json_object_object_get_ex(notify_params_member_jobj, "devname", &notify_params_member_item_jobj);

        if(SAME_STR != strcmp(net_notify_params, json_object_get_string(notify_params_member_item_jobj)))
        {
            return request_rpc_num;
        }
    }
    else
    {
        RPTERR("No response for notification from %s!", notify_method);
        return request_rpc_num;
    }

    for(i = 0; i < NOTIFY_ITEM_NUMS; i++)
    {
        request_rpc_num = generate_request_rpc(notify_params_member_jobj, &notify_table[i], request_rpc);
        if(request_rpc_num)
        {
            return request_rpc_num;
        }
    }

    return request_rpc_num;
}

static void send_request_rpc(od_msg_handle msg_handle, od_msg_t *msg, struct json_object *request_rpc, notify_params *params)
{
    msg->data_len = strlen(json_object_get_string(request_rpc)) + 1;
    strncpy(msg->data, json_object_get_string(request_rpc), 5*RECV_DATA_LEN-1);
    msg->src_id = params->notify_response_id;
    msg->dst_id = params->dst_id;
    //msg.cmd_id = 11;
    od_msg_send(msg_handle, msg, 0);
    od_msg_receive(msg_handle, msg, 0);
}

void  notify_dispose_thread(void *arg)
{
    notify_params params = *(notify_params *)arg;
    od_msg_t msg;
    od_msg_handle msg_handle = NULL;

    od_msg_t notify_msg;
    od_msg_handle notify_msg_handle = NULL;
    char *data = od_calloc(1, 5*RECV_DATA_LEN);
    char *notify_data = od_calloc(1, 5*RECV_DATA_LEN);

    struct json_object * request_rpc[REQUEST_RPC_NUM];
    int rpc_num = 0;
    int ret = OD_ERROR;
    int i;

    jsonrpc_request_t notify;
    memset(&msg, 0, sizeof(od_msg_t));
    msg.data = data;
    msg_handle = od_msg_create_fix_trans(params.post_name, params.notify_response_id, MSG_MQ_PRIO_MIDDLE, 0);

    memset(&notify_msg, 0, sizeof(od_msg_t));
    notify_msg.data = notify_data;
    notify_msg_handle = od_msg_create_fix_trans(params.post_name, params.notify_id, MSG_MQ_PRIO_MIDDLE, 0);

    while(1)
    {
        ret = notification_receiveandparse(notify_msg_handle, &notify_msg, &notify);
        if(ret == OD_OK)
        {
            RPTWRN("recv %s", notify_msg.data);
            rpc_num = makeup_request_rpc(notify.method, notify.jobj_params, request_rpc);
            for(i = 0; i < rpc_num; i++)
            {
                RPTWRN("send rpc %s", json_object_to_json_string(request_rpc[i]));
                send_request_rpc(msg_handle, &msg, request_rpc[i], &params);
                json_object_put(request_rpc[i]);
            }
        }

        od_msleep(10);
    }

    if(msg_handle != NULL)
    {
        od_msg_destroy(msg_handle);
    }

    if(notify_msg_handle != NULL)
    {
        od_msg_destroy(notify_msg_handle);
    }

    if(data != NULL)
    {
        od_free(data);
    }

    if(notify_data != NULL)
    {
        od_free(notify_data);
    }
}

